package file_api

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"io"
	"leading/global"
	"leading/models"
	"leading/models/res"
	"leading/service"
	"leading/utils"
	"mime/multipart"
	"os"
	"path"
	"strconv"
)

type FileApi struct {
}

func saveFile(fileHeader *multipart.FileHeader) error {
	src, err := fileHeader.Open()
	if err != nil {
		return err
	}
	defer src.Close()
	// 文件目录
	uploadDir := "upload"

	// 确保文件目录是存在
	err = os.MkdirAll(uploadDir, os.ModePerm)
	if err != nil {
		return err
	}
	// 文件路径
	dstPath := path.Join(uploadDir, fileHeader.Filename)
	// 创建文件
	dst, err := os.Create(dstPath)
	if err != nil {
		return err
	}
	defer dst.Close()

	// 进行复制
	_, err = io.Copy(dst, src)
	if err != nil {
		return err
	}
	return nil
}

// 上传文件
func (FileApi) Upload(c *gin.Context) {
	// 验证参数
	var query UploadFIleQuery
	var user models.UserModel
	Res, _ := c.Get("user")
	user = Res.(models.UserModel)
	if err := c.ShouldBind(&query); err != nil {
		res.FailWithoutData(err.Error(), c)
		return
	}
	form, err := c.MultipartForm()
	if err != nil {
		res.FailWithoutData(err.Error(), c)
		return
	}
	files, _ := form.File["files"]
	if len(files) == 0 {
		res.FailWithoutData("文件不能为空", c)
		return
	}
	// 判断目录是否存在
	var dirId string = query.FileId
	tx := global.DB.Begin()
	if query.FileId > "0" {
		var hasDir = service.IsDirExist(query.FileId, user.ID)
		// 创建目录
		if !hasDir {
			var fileModel = &models.FileModel{
				UserID: user.ID,
				FileId: "0",
				IsDir:  1,
				Name:   "user_" + strconv.Itoa(int(user.ID)),
			}
			tx.Create(&fileModel)
			dirId = strconv.Itoa(int(fileModel.ID))
		}
	}

	// 所有文件的大小
	var totalSize int64 = 0

	for _, file := range files {
		//
		totalSize += file.Size
		size := file.Size
		if size > (global.Config.Upload.FileSize << 20) {
			res.FailWithoutData("文件过大", c)
			return
		}
		hasSize := user.TotalSize - user.UseSize
		if size > int64(hasSize) {
			res.FailWithoutData("内存不足", c)
			return
		}

		err := saveFile(file)
		if err != nil {
			res.FailWithoutData("文件保存失败", c)
			return
		}

		var fileModel models.FileModel
		fileModel.FileId = dirId
		fileModel.IsDir = 0
		fileModel.Ext = utils.GetFileExt(file.Filename)
		fileModel.Name = file.Filename
		fileModel.UserID = user.ID
		fileModel.Size = uint(file.Size)
		tx.Create(&fileModel)

		// 需要查询用户的剩余容量
		err = global.DB.Where(&user).First(&user).Error
		if err != nil {
			res.FailWithoutData(err.Error(), c)
			tx.Rollback()
			return
		}
		// 更新用户的使用容量
		global.DB.Model(&user).Update("use_size", uint(totalSize)+user.UseSize)
		tx.Commit()
	}

	res.OKWithoutMsg(nil, c)
}

// 文件重命名
func (FileApi) RenameFile(c *gin.Context) {
	var query ReNameFileQuery
	if err := c.ShouldBind(&query); err != nil {
		res.FailWithoutData(err.Error(), c)
		return
	}
	var user models.UserModel
	Res, _ := c.Get("user")
	user = Res.(models.UserModel)
	var fileModel models.FileModel
	// 查询文件是否存在
	num := global.DB.Where("id=? and user_id = ?", query.FileId, user.ID).First(&fileModel).RowsAffected
	if num <= 0 {
		res.FailWithoutData("文件不存在", c)
		return
	}

	// 更新文件名
	err := global.DB.Model(&fileModel).Where("id=? and user_id = ?", query.FileId, user.ID).Update("name", query.Name).Error
	if err != nil {
		res.FailWithoutData("更新失败", c)
		return
	}
	res.OKWithoutMsg(nil, c)
}

// 获取文件列表
func (FileApi) GetList(c *gin.Context) {
	var query ListFileQuery
	if err := c.ShouldBind(&query); err != nil {
		res.FailWithoutData("参数有错", c)
		return
	}
	var user models.UserModel
	Res, _ := c.Get("user")
	user = Res.(models.UserModel)

	yes := service.IsFileExit(query.FileID, user.ID)
	fmt.Println("yes:", yes)
	if !yes {
		res.FailWithoutData("文件不存在", c)
		return
	}
	// 查询目录下的所有文件
	var files []models.FileModel

	err := global.DB.Where("file_id = ? and name like ?", query.FileID, "%"+query.Type).Order("name desc").Find(&files).Error
	if err != nil {
		res.FailWithoutData(err.Error(), c)
		return
	}
	res.OKWithoutMsg(gin.H{"list": files}, c)
}

// 搜索
func (FileApi) DoSearch(c *gin.Context) {
	var query SearchFileQuery

	if err := c.ShouldBind(&query); err != nil {
		res.FailWithoutData("参数有错", c)
		return
	}
	var user models.UserModel
	Res, _ := c.Get("user")
	user = Res.(models.UserModel)
	var files []models.FileModel
	err := global.DB.Model(&models.FileModel{}).Where("name like ? and user_id = ?", "%"+query.Desc+"%", user.ID).Find(&files).Error
	if err != nil {
		res.FailWithoutData(err.Error(), c)
		return
	}
	res.OKWithoutMsg(gin.H{"list": files}, c)
}

// 删除
func (FileApi) DoDelete(c *gin.Context) {
	var query DeleteFileQuery
	if err := c.ShouldBind(&query); err != nil {
		res.FailWithoutData(err.Error(), c)
		return
	}

	var user models.UserModel
	Res, _ := c.Get("user")
	user = Res.(models.UserModel)

	// 获取当前删除的文件
	var file models.FileModel
	err := global.DB.Model(&models.FileModel{}).Where("id = ? and user_id = ?", query.Id, user.ID).First(&file).Error
	if err != nil {
		res.FailWithoutData(err.Error(), c)
		return
	}

	var isDir uint = file.IsDir
	var files []models.FileModel
	var totalSize uint = user.UseSize
	tx := global.DB.Begin()

	if isDir == 1 {
		// 获取目录下所有文件
		err := global.DB.Where("file_id= ? and user_id = ?", file.ID, user.ID).Find(&files).Error
		if err != nil {
			res.FailWithoutData(err.Error(), c)
			return
		}
		// 删除目录下文件
		err = tx.Where("file_id = ? and user_id = ?", file.ID, user.ID).Delete(&models.FileModel{}).Error
		if err != nil {
			res.FailWithoutData("删除失败", c)
			tx.Rollback()
			return
		}
	} else {
		err := tx.Where("id= ? and user_id = ?", file.ID, user.ID).Find(&files).Error
		if err != nil {
			res.FailWithoutData(err.Error(), c)
			tx.Rollback()
			return
		}
	}
	// 文件大小
	for _, fileModel := range files {
		totalSize -= fileModel.Size
	}
	// 更新内存
	err = tx.Model(&models.UserModel{}).Where("id= ?", user.ID).Update("use_size", uint(totalSize)).Error
	// 删除目录
	if err != nil {
		res.FailWithoutData(err.Error(), c)
		tx.Rollback()
		return
	}
	err = tx.Where("id =?", query.Id).Delete(&models.FileModel{}).Error
	if err != nil {
		res.FailWithoutData("删除失败", c)
		tx.Rollback()
		return
	}
	tx.Commit()
	res.OKWithoutMsg("删除成功", c)
}
